#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <arpa/inet.h>

#include "icar.h"
#include "icar_end_msg.h"
#include "icar_log.h"
#include "icar_utils.h"

static int handle_stdmsg(int fd, uint8_t *msg, size_t size);
static int parse_obd_ex(int fd, uint8_t *msg, size_t size);
static int parse_fault_ex(int fd, uint8_t *msg, size_t size);

int
icar_parse_end(int fd, int id, uint8_t *msg, size_t size)
{
	if (id == 0x24) {
		icar_daemon(LOG_DEBUG, "First stdandard message!");
		parse_std_msg(fd, msg, size);
	}
	else if (id == 0x23)
		handle_stdmsg(fd, msg, size);

	return 0;
}

int
parse_std_msg(int fd, uint8_t *msg, size_t size)
{
	char number[VALUE_LEN] = { 0 };
	char buf[VALUE_LEN] = { 0 };
	int i;
	uint8_t *p;
	uint8_t extend;

	icar_pkg_print(msg, size);

	p = buf;
	i = 0;

	if (i + 6 >= size)
		return -1;
	i++;

	memcpy(buf, &msg[i], 5);
	i += 5;
	snprintf(number, sizeof(number), "%02x%02x%02x%02x%02x", 
			p[0] & 0xff, p[1] & 0xff, 
			p[2] & 0xff, p[3] & 0xff, p[4] & 0xff);
	icar_daemon(LOG_DEBUG, "Vehicle number: %s", number);

	if (i + 3 >= size)
		return -1;

	memcpy(buf, &msg[i], 3);
	i += 3;

	icar_daemon(LOG_DEBUG, "Time: %02x:%02x:%02x", p[0], p[1], p[2]);

	if (i + 3 >= size)
		return -1;

	memcpy(buf, &msg[i], 3);
	i += 3;

	icar_daemon(LOG_DEBUG, "Date: 20%02x-%02x-%02x", p[2], p[1], p[0]);

	if (i + 4 >= size)
		return -1;
	memcpy(buf, &msg[i], 4);
	i += 4;

	icar_daemon(LOG_DEBUG, "Latitude value: %02x*%02x.%02x%02x",
			p[0], p[1], p[2], p[3]);

	if (i + 1 >= size)
		return -1;

	icar_daemon(LOG_DEBUG, "Battery capacity: %02X", msg[i]);
	i++;

	if (i + 5 >= size)
		return -1;

	memcpy(buf, &msg[i], 5);
	i += 5;

	icar_daemon(LOG_DEBUG, "%s longitude, %s latitude, %s. longtitude: %02x%x*%x%x.%x%02x%x",
			p[4] & 0x8 ? "East" : "West", p[4] & 0x4 ? "North" : "South", p[4] & 0x2 ? "A" : "V",
			p[0], p[1] >> 4 & 0xf, p[1] & 0xf, p[2] >> 4 & 0xf, p[2] & 0xf,
			p[3], p[4] >> 4 & 0xf);

	if (i + 3 >= size)
		return -1;

	memcpy(buf, &msg[i], 3);
	i += 3;

	icar_daemon(LOG_DEBUG, "Speed: %02x%x, direction: %x%02x", p[0], p[1] >> 4 & 0xf, p[1] & 0xf, p[2]);

	if (i + 4 >= size)
		return -1;

	icar_daemon(LOG_DEBUG, "Vehicle status: %02x%02x%02x%02x", p[0], p[1], p[2], p[3]);
	i += 4;

	if (i + 1 >= size)
		return -1;
	icar_daemon(LOG_DEBUG, "User alarm flag: %02x", msg[i]);
	i++;

	if (i + 1 >= size)
		return -1;

	icar_daemon(LOG_DEBUG, "Alarm setup flag: %02x", msg[i]);
	i++;

	if (i + 2 >= size)
		return -1;
	icar_daemon(LOG_DEBUG, "Alarm setup status: %02x%02x", msg[i], msg[i+1]);
	i += 2;

	if (i + 1 >= size)
		return -1;

	icar_daemon(LOG_DEBUG, "Milepost: %02x", msg[i]);
	i++;


	if (i + 10 >= size)
		return -1;

	i += 9;

	extend = msg[i];
	i++;
	switch (extend) {
	case 0:
		icar_daemon(LOG_DEBUG, "No extend data");
		break;
	case 1:
		icar_daemon(LOG_DEBUG, "OBD extend data");
		break;
	case 2:
		icar_daemon(LOG_DEBUG, "Fault extend data");
		break;
	default:
		icar_daemon(LOG_ERR, "Uknown extend: %d\n", extend);
		break;
	}

	return 0;
}


static int
handle_stdmsg(int fd, uint8_t *msg, size_t size)
{
	int count;
	char number[VALUE_LEN] = { 0 };
	uint8_t buf[VALUE_LEN] = { 0 };
	uint8_t *p;
	uint32_t value = 0;

	count = 0;
	p = buf;
	icar_pkg_print(msg, size);

	if (size <= 6)
		goto handle_failed;
	memcpy(buf, &msg[1], 5);
	count += 6;
	snprintf(number, sizeof(number), "%02x%02x%02x%02x%02x", 
			p[0] & 0xff,
			p[1] & 0xff,
			p[2] & 0xff,
			p[3] & 0xff,
			p[4] & 0xff);

	icar_daemon(LOG_DEBUG, "Vehicle number is [%s]", number);

	if (count+3 >= size)
		goto handle_failed;

	memcpy(buf, &msg[count], 3);
	count += 3;
	icar_daemon(LOG_DEBUG, "Time: %02x:%02x:%02x", p[0] & 0xff, p[1] & 0xff, p[2] & 0xff);

	if (count + 3>= size)
		goto handle_failed;

	memcpy(buf, &msg[count], 3);
	count += 3;
	icar_daemon(LOG_DEBUG, "Date: 20%02x-%02x-%02x", p[2] & 0xff, p[1] & 0xff, p[0] & 0xff);

	if (count + 4>= size)
		goto handle_failed;
	memcpy(buf, &msg[count], 4);
	count += 4;
	icar_daemon(LOG_DEBUG, "Latitude value: %02x*%02x.%02x%02x", p[0], p[1], p[2], p[3]);

	if (count+1 >= size)
		goto handle_failed;

	icar_daemon(LOG_DEBUG, "Battery: %02x", msg[count]);
	count++;


	if (count+5 >= size)
		goto handle_failed;

	memcpy(buf, &msg[count], 5);
	count += 5;

	icar_daemon(LOG_DEBUG, "%s longtitude, %s latitude, %s. longitude: %02x%x*%x%x.%x%02x%x", 
			p[4] & 0x8 ? "East" : "West", p[4] & 0x4 ? "North" : "South", p[4] & 0x2 ? "A" : "V",
			p[0], p[1] >> 4 & 0xf, p[1] & 0xf, p[2] >> 4 & 0xf, p[2] & 0xf, p[3], p[4] >> 4 & 0xf);

	if (count + 3 >= size)
		goto handle_failed;

	memcpy(buf, &msg[count], 3);
	count += 3;
	icar_daemon(LOG_DEBUG, "Current speed: %x%x, direction: %x%02x",
			p[0], p[1] >> 4 & 0xf, p[1] & 0xf, p[2]);

	if (count +4 >= size)
		goto handle_failed;

	memcpy(buf, &msg[count], 4);
	count += 4;
	icar_daemon(LOG_DEBUG, "Vehicle status: %02x%02x%02x%02x", p[0] & 0xff,p[1] & 0xff, p[2] & 0xff, p[3] & 0xff);

	if (count + 1 >= size)
		goto handle_failed;
	icar_daemon(LOG_DEBUG, "User alarm flag: %02x", msg[count]);
	count++;

	if (count + 1 >= size)
		goto handle_failed;
	icar_daemon(LOG_DEBUG, "Alarm setup flag: %02x", msg[count]);
	count++;

	if (count + 2 >= size)
		goto handle_failed;

	icar_daemon(LOG_DEBUG, "Alarm setup status: %02x%02x", msg[count], msg[count+1]);
	count += 2;

	if (count +3 >= size)
		goto handle_failed;

	memcpy(buf, &msg[count], 3);
	count += 3;
	value = p[0] << 16 | p[1] << 8 | p[2];
	icar_daemon(LOG_DEBUG, "Mileage value: %d", value);

	if (count + 1 >= size)
		goto  handle_failed;

	switch (msg[count]) {
	case 0x00:
		{
			icar_daemon(LOG_DEBUG, "NO extend data");
			count++;
			if (count + 2 >= size)
				goto handle_failed;
			icar_daemon(LOG_DEBUG, "Contry code: %d", msg[count] << 8 | msg[count+1]);
			count += 2;

			if (count + 2 >= size)
				goto handle_failed;

			icar_daemon(LOG_DEBUG, "Business number: %d", msg[count] << 8 | msg[count+1]);
			count += 2;

			if (count + 3 >= size)
				goto handle_failed;

			icar_daemon(LOG_DEBUG, "Message ending: %c%c%d%d", msg[count], msg[count+1], msg[count+2] >> 4 & 0xf, msg[count+2] & 0xf);
			count += 3;

			if (count+1 == size)
				icar_daemon(LOG_DEBUG, "Record number: %d", msg[count]);

		}
		break;
	case 0x01:
		count++;
		parse_obd_ex(fd, &msg[count], size-count);
		break;
	case 0x02:
		count++;
		parse_fault_ex(fd, &msg[count], size-count);
		break;
	}

	return 0;
handle_failed:
	icar_daemon(LOG_ERR, "Not standard message");
	return -1;
}

static int
parse_obd_ex(int fd, uint8_t *msg, size_t size)
{
	return 0;
}

static int
parse_fault_ex(int fd, uint8_t *msg, size_t size)
{
	return 0;
}
